package org.footballmanager.pandafootball.common.converter;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @author chenjian
 * @since 2017年10月18日下午5:17:22
 */
public class UniversalEnumHandler<E extends BaseEnum<Integer>> extends BaseTypeHandler<E> {
	private Class<E> type;
	private E [] enums;
	
	/** 
	 * 设置配置文件设置的转换类以及枚举类内容，供其他方法更便捷高效的实现 
	 * @param type 配置文件中设置的转换类 
	 */
	public UniversalEnumHandler(Class<E> type) {
		if (type == null)
			throw new IllegalArgumentException("Type argument cannot be null");
		this.type = type;
		this.enums = type.getEnumConstants();
		if (this.enums == null)
			throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
	}

	/**
	 * 设置非空参数
	 * @param ps 参数
	 * @param i 参数
	 * @param parameter 参数
	 * @param jdbcType 参数
	 * @throws SQLException 异常
	 */
	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
		//BaseTypeHandler已经帮我们做了parameter的null判断
		ps.setInt(i, parameter.getValue());
	}

	/**
	 * 获取空值结果
	 * @param rs 参数
	 * @param columnName 参数
	 * @return 返回值
	 * @throws SQLException 异常
	 */
	@Override
	public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
		// 根据数据库存储类型决定获取类型，本例子中数据库中存放String类型
		Integer i = rs.getInt(columnName);
		if (rs.wasNull()) {
			return null;
		} else {
			// 根据数据库中的value值，定位PersonType子类
			return locateEnumStatus(i);
		}
	}

	/**
	 * 获取空值结果
	 * @param rs 参数
	 * @param columnIndex 参数
	 * @return 返回值
	 * @throws SQLException 异常
	 */
	@Override
	public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
		// 根据数据库存储类型决定获取类型，本例子中数据库中存放String类型
		Integer i = rs.getInt(columnIndex);
		if (rs.wasNull()) {
			return null;
		} else {
			// 根据数据库中的value值，定位PersonType子类
			return locateEnumStatus(i);
		}
	}

	/**
	 * 获取空值结果
	 * @param cs 参数
	 * @param columnIndex 参数
	 * @return 返回值
	 * @throws SQLException 异常
	 */
	@Override
	public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
		// 根据数据库存储类型决定获取类型，本例子中数据库中存放String类型
		Integer i = cs.getInt(columnIndex);
		if (cs.wasNull()) {
			return null;
		} else {
			// 根据数据库中的value值，定位PersonType子类
			return locateEnumStatus(i);
		}
	}

	 /** 
	 * 枚举类型转换，由于构造函数获取了枚举的子类enums，让遍历更加高效快捷 
	 * @param value 数据库中存储的自定义value属性 
	 * @return value对应的枚举类 
	 */
	private E locateEnumStatus(Integer value) {
		for(E e : enums) {
			if(e.getValue().equals(value)) {
				return e;
			}
		}
		throw new IllegalArgumentException("未知的枚举类型：" + value + ",请核对" + type.getSimpleName());
	}
}

